home *** CD-ROM | disk | FTP | other *** search
- Subject: Re: Initializing an Extension
- Sent: 3/9/96 10:21 AM
- Received: 3/11/96 8:27 AM
- From: Greg Friedman, friedman@cognosis.com
- Reply-To: ODF-Interest@CILabs.ORG
- To: OpenDoc Development Framework Discussion List, ODF-Interest@CILabs.
-
- Bernhard asked:
-
- >
- >Why would you want to register the part with the
- >extension via its init method? Shouldn't it be the other way around?
- >The part registers the extension. If the part wants to get access to it, it
- >calls GetExtensionManager( /* no ev in D11 Damon */ )->AcquireExtension(
- >ev, kMyExtName )?
-
- There are two objects involved in an extension transaction: the ODObject
- that owns and creates the extension, and the ODObject that requests and
- acquires the extension. Note that I say ODObject, not ODPart, since the
- extension API is introduced in ODObject, from which ODPart derives. The
- interactions and responsibilities, described from the perspective of the
- owning object, are as follows:
-
- Owning ODObject (assume a part developed in ODF):
-
- At startup, register the extension's creation function with the extension
- manager. (In ODF d11, the registration function takes only a function
- pointer as a parameter. In ODF 1, we've added a reference constant and a
- boolean indicating whether the extension should be cached by the extension
- manager when its reference count drops to zero. This latter parameter was
- added to reduce the overhead of accessing extensions such as the semantic
- interface which are required and released frequently. Many extensions will
- be acquired once and released once. Caching won't apply in these cases.)
-
- When a client is interested in the availability of a specific extension, it
- calls the HasExtension method of the owning part. HasExtension is
- encapsulated in the extension manager: it returns TRUE if an extension with
- the specified name has been registered, and FALSE if it hasn't.
-
- When a client wants to acquire the extension, it calls the AcquireExtension
- method of the owning part. The extension manager looks for an existing
- extension with the specified name. If it finds one, it increments the
- reference count by calling extension::Acquire, and returns the extension.
- If it doesn't find one, it looks for a creation function that maps to the
- specified name. If it finds on, it calls it.
-
- The creation function creates, initializes, and returns an instance of the
- requested extension. This should always involve calling an Init method
- defined by the extension. I believe this is the method you are asking
- about, so I'll go into a little bit of detail.
-
- The function of an extension is to extend the API of the object that owns
- it. If you have, for example, a part that can perform spell checking on
- text runs it displays in its own frames, you may decide to make the spell
- checking service available to other parts. This would require the
- introduction of new API to some object that other parts can get access to.
- One way to do this would be to create an extension that has methods
- BeginSpellingSession, FindNextError, ReplaceAndContinue, GetStatistics,
- EndSpellingSession, etc. You might decide to introduce this API by
- declaring a new extension type. Clients who want to use the service can
- then ask parts in their document whether or not they have the extension
- and, if they find one that does, they can acquire it at need.
-
- The spell checking functionality is implemented in the part that owns the
- spelling extension. The extension is just API that calls into the part to
- get the work done. This makes the sense when you remember that an extension
- "extends the API" of the object that owns it. This is why you provide a
- back pointer to the owning object when you create an extension: so the
- extension can call into the owning object.
-
- The object that created and owns the extension is called the "base" object.
- It is important to remember, when writing an extension, that an extension's
- base might go away while some client of the extension still has a reference
- to an active extension. An example: In the spell checking example above,
- some part acquires and keeps a spell checking extension. The user decides
- to delete the spell checking part from the document. The spell checking
- part, having been developed using ODF 1, correctly implements the extension
- recipe, and calls the "BaseRemoved" method of the spelling extension that
- it provided. The spelling part is then destroyed, but the extension is not.
- Now, whenever the spelling extension is called, it cannot call into its
- base, since the base no longer exists. The correct implementation for this
- behavior is for an extension to call IsValid before attempting to call into
- its base object. IsValid will return FALSE if the extension's base has been
- removed.
-
- Moving on to the rest of the extension protocol:
-
- When a client is done with an extension, it calls the Release method of the
- extension (* Not the ReleaseExtension method of the part that provided the
- extension *). This is an important point: extensions are acquired from the
- objects that own them. They are released directly, not through their owner.
- This is particularly important given the above description of how a part
- might go away before its extensions have been released.
-
- When an extension is released it should call its inherited
- ODExtension::Release method. This method decrements the reference count of
- the extension. If the reference count has dropped to zero, and the base has
- not been removed, the base object's ReleaseExtension method is called. It
- does not handle the case where the reference count has dropped to zero, but
- the base has been removed. In your extension, you should override release
- and do something like the following:
-
-
- FW_Boolean isValid = somSelf->IsValid(ev);
-
- FW_OSemanticInterface_parent_ODSemanticInterface_Release(somSelf,ev);
-
- if (!isValid && somSelf->GetRefCount(ev) == 0)
- delete somSelf;
-
- The call to IsValid is made before calling the parent method, because the
- parent method might cause the extension to be destroyed if the reference
- count drops to zero and the base is valid. My experience suggests that it
- is not always a good idea to use an object pointer after the object has
- been destroyed.
-
- In your question, you suggest that if a part wants to get to an extension
- that it owns, it should call its own AcquireExtension method. This is
- correct. To facilitate this, we've extended the internal AcquireExtension
- API by adding a boolean to the method indicating whether or not the
- extension manager should create an instance of the extension if one doesn't
- exist. This means that it will be possible to acquire the extension if and
- only if it already exists. This is useful for our internal implementation
- of a semantic interface. It may or may not apply ot the work you are doing.
- Since the parameter is part of the internal API, it is not available to
- external extension clients.
-
- I hope this addresses your questions. If not, I'll try to provide more
- specific information about the areas you find confusing.
-
- >p.s. "Every SOM call can produce a SOM Exception." I am worried that
- >SOM error checking is not consistently apparent. Do I have reason to be?
-
- Jim already addressed this, but I'll add a couple of comments. Whenever you
- call from ODF into SOM, the possibility exists that a som error returned
- through the ODF/SOM boundary will converted to an ODF exception and will be
- rethrown. The danger here is that it is fatal to allow the ODF exception to
- propogate back out into SOM. This means that you should protect all of your
- extensions SOM entry points with try/catch blocks that guarantee that an
- ODF exception won't make it back out into SOM. Your entry points should
- look something like:
-
- FW_TRY
- {
- ... do your thing
- }
- FW_CATCH_BEGIN
- FW_CATCH_REFERENCE(FW_XException, exception)
- {
- FW_SetException(ev, exception);
- }
- FW_CATCH_EVERYTHING()
- {
- FW_SetEvError(ev, kODErrUndefined);
- }
- FW_CATCH_END
-
- I hope this helps,
-
- gsf.
-
-
- ___________________________________________________________
- Greg Friedman ODF Engineering Apple Computer
-
-